package learn.up.java.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 实现volatile变量的原子性
 * 在多线程环境下安全地使用volatile变量，需要同时满足
 * 1.对变量的写入操作不依赖其当前值
 *   不满足：i++; i = i*5;
 *   满足：boolean变量，记录温度变化的值 
 * 2.该变量没有包含在具有其他变量的不等式中
 *   不满足：a > b
 *   
 * @author jw
 *
 */
public class VolatileDemo {
	
	public static void main(String[] args) {
		VolatileDemo demo = new VolatileDemo();
		for (int i = 0; i < 500; i++) {
			new Thread(demo.new ThreadDemo()).start();
		}
		/*
		 * 如果活动线程大于1，说明除了Main线程之外还有计算线程在运行，所以要
		 * 让出当前主线程，让计算线程执行结束才打印
		 */
		while (Thread.activeCount() > 1)
			Thread.yield();
		System.out.println(demo.amount);
	}
	
	private Lock lock = new ReentrantLock();
	private int amount = 0;
	
	public class ThreadDemo extends Thread {

		@Override
		public void run() {
			increase();
		}
		
	}
	
	/**
	 * 1.可以使用synchronized()实现原子性
	 * 2.使用ReentrantLock实现同步锁
	 * 
	 */
	public void increase() {
		/*
		 * 需要实现原子操作的语句块放入try-finally中，要保证必须
		 * 释放锁，因为复合操作语句可能产生异常，java官方文档推荐的
		 * 写法
		 */
		lock.lock();
		try {
			this.amount++;
		} finally {
			lock.unlock();
		}
		
		
	}

	public int getAmount() {
		return amount;
	}

	public void setAmount(int amount) {
		this.amount = amount;
	}
}
 
